/*
 * REF.h
 *
 *  Created on: May 19, 2016
 *      Author: Lucifer
 */

#ifndef __REF_H__
#define __REF_H__

#include <stdio.h>

namespace BFX {

template<class T>
class REF {
private:
	T* _pt;

public:
	/**
	 * Initializes a default (NULL) instance.
	 */
	REF() :
			_pt(NULL) {
	}
	/**
	 * Initializes a new instance by specified interface pointer.
	 * @param pt
	 */
	REF(const T* pt) {
		_pt = (T*) pt;
		if (_pt)
			_pt->acquireRef();
	}
	/**
	 * Initializes a new instance by other instance.
	 * @param ref
	 */
	REF(const REF& ref) :
			_pt(ref._pt) {
		if (_pt)
			_pt->acquireRef();
	}
	~REF(void) {
		if (_pt)
			_pt->releaseRef();
	}

	/**
	 * Assigns an other instance to the current instance.
	 * @param ref
	 * @return
	 */
	REF& operator=(const REF& ref) {
		T* ptOld = _pt;
		_pt = ref._pt;
		if (_pt)
			_pt->acquireRef();
		if (ptOld)
			ptOld->releaseRef();
		return *this;
	}
	/**
	 * Assigns a interface pointer to the current instance.
	 * @param pt
	 * @return
	 */
	REF& operator=(const T* pt) {
		T* ptOld = _pt;
		_pt = (T*) pt;
		if (_pt)
			_pt->acquireRef();
		if (ptOld)
			ptOld->releaseRef();
		return *this;
	}

	/**
	 *Retrieves a reference to the type specified by the current template
	 */
	T& operator*() const {
		return *_pt;
	}
	/**
	 * Retrieves a pointer to the type specified by the current template
	 * parameter.
	 * @return
	 */
	T* operator->() const {
		return _pt;
	}
	operator T*() const {
		return _pt;
	}

	/**
	 * Indicates whether an instance equals to a pointer.
	 * @param ref
	 * @param pt
	 * @return
	 */
	friend bool operator==(const REF& ref, T* pt) {
		return ref._pt == pt;
	}
	friend bool operator==(T* pt, const REF& ref) {
		return ref == pt;
	}

	/**
	 * Indicates whether an instance not equals to a pointer.
	 * @param ref
	 * @param pt
	 * @return
	 */
	friend bool operator!=(const REF& ref, T* pt) {
		return ref._pt != pt;
	}
	friend bool operator!=(T* pt, const REF& ref) {
		return ref != pt;
	}
};

} /* namespace BFX */

#endif /* __REF_H__ */
